<?php

/*
 *  This file is part of Urd.
 *
 *  Urd is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *  Urd is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. See the file "COPYING". If it does not
 *  exist, see <http://www.gnu.org/licenses/>.
 *
 * $LastChangedDate: 2008-12-22 00:28:59 +0100 (Mon, 22 Dec 2008) $
 * $Rev: 358 $
 * $Author: gavinspearhead $
 * $Id: urdd_command.php 358 2008-12-21 23:28:59Z gavinspearhead $
 */


// This is an include-only file:
if (!defined('ORIGINAL_PAGE')) die('This file cannot be accessed directly.');


$pathcmd = realpath(dirname(__FILE__));


require_once "$pathcmd/urdd_protocol.php";
require_once "$pathcmd/../functions/urd_log.php";
require_once "$pathcmd/../config.php";
require_once "$pathcmd/../functions/defines.php";
require_once "$pathcmd/urdd_help.php";
require_once "$pathcmd/urdd_error.php";


function split_args($args)
{
    $arg_list = array();
    $item = '';
    $quote = '';
    $len = strlen($args);
    for ($i = 0; $i < $len; $i++) {
        $c = $args[$i];
        if ($c == $quote && $quote != '') {
            $quote = ''; continue;
        }
        else if (($c == '"' || $c == '\'') && $quote == '') {
                $quote = $c; continue;
        } elseif ($c == '\\') { 
            $i++; 
            continue;
        }
        elseif ($c == ' ' && $quote == '') {
            if (strlen($item) == 0) 
                continue;
            else {
                $arg_list[] = $item; 
                $item = '';
            }
        } else {
            $item .= $c;
        }
    }
    if (strlen($item) != 0)
        $arg_list[] = $item;
    return $arg_list;
}


function do_command(DatabaseConnection $db, $line, &$response, conn_list &$conn_list, $sock, server_data &$servers, $username=NULL, $priority=NULL, $internal=FALSE)
    //if internal == TRUE, download_action can be used same as download
{
    //echo_debug_function(DEBUG_SERVER, __FUNCTION__);
    assert(is_bool($internal));
    global $responses, $commands_list, $config;
    $isadmin = FALSE;
    $response = '';
    $elems = preg_split('/[\s]+/', $line, 2);
    $cmd_str = strtoupper($elems[0]);
    $args = (isset($elems[1])) ? $elems[1] : NULL;
    //  $arg_list = preg_split('/[\s]+/', $args);
    $arg_list = split_args($args);
    $cmd = match_command($cmd_str);
    if ($cmd === FALSE) {
        $response = sprintf($responses[500], "'$cmd_str'");
        return URDD_ERROR;
    }
    if ($username === NULL && $sock !== NULL) {
        if ($cmd->needs_auth()) {
            if ($conn_list->check_authorised($sock) !== TRUE) {
                $response = $responses[530];
                return URDD_NOERROR;
            }
        }
        $username = $conn_list->get_username($sock);
    }
    
    if ($cmd->needs_admin()) {
        if (is_admin($db, $username) !== TRUE) {
            $response = $responses[532];
            return URDD_NOERROR;
        } else
            $isadmin = TRUE;

    }
    if ($priority === NULL)
        $priority = DEFAULT_PRIORITY;
    
    if ($config['disable_nntp'] === TRUE && $cmd->needs_nntp() ) {
        $response = $responses[410];
        return URDD_NOERROR;
    }
    
    // TODO fix the commands to a better format

    switch($cmd->get_code()) {
    case COMMAND_REPEAT_LAST_COMMAND:
        $conn =& $conn_list->get_conn($sock);
        $line = $conn->get_last_cmd();
        $rv = do_command($db, $line, $response, $conn_list, $sock, $servers, $username, $priority, FALSE);
        if ($rv != URDD_NOERROR) 
            return $rv;
        else
            return URDD_ERROR;
        break;
    case COMMAND_USER: 
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        $username = trim($arg);
        if (valid_username($username)) {
            $conn_list->add_username($sock, $username);
            $response = $responses[331];
        } else
            $response = $responses[501];
        return URDD_NOERROR;
    case COMMAND_PASS:
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        $res = $conn_list->verify_password_db($db, $sock, $arg);
        if ($res){
            $response = $responses[240];
        } else {
            write_log("Invalid password provided for $username", LOG_NOTICE);
            $response = $responses[530];
        }
        return URDD_NOERROR;
    case COMMAND_DOWNLOAD_ACTION: // if run from the command line it's a no-op too 
        if ($internal === FALSE) {
            $response = $responses[231];
            return URDD_NOERROR;
        } // else FALL THROUGH
    case COMMAND_DOWNLOAD:
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        if (is_numeric($arg))
            $response = restart_download($servers, $username, $db, $arg, $priority);
        else if (strtolower($arg) == 'preview')
            $response = create_download($db, $servers, $username, TRUE);
        else
            $response = create_download($db, $servers, $username, FALSE);
        return URDD_NOERROR;
    case COMMAND_MAKE_NZB: 
        $response = create_make_nzb($db, $servers, $username, $priority-1);
        return URDD_NOERROR;
    case COMMAND_SHUTDOWN:
        $response = $responses[222];
        return URDD_SHUTDOWN;
    case COMMAND_RESTART:
        $response = $responses[223];
        return URDD_RESTART;
    case COMMAND_UNSCHEDULE:
        try {
            $response = do_unschedule($db, $arg_list, $servers, $username);
        } catch (exception $e) {
            $response = $responses[501];
        }
        return URDD_NOERROR;
    case COMMAND_SCHEDULE:
        try {
            $response = do_schedule($db, $arg_list, $servers, $username);
        } catch (exception $e) {
            $response = $responses[501];
        }
        return URDD_NOERROR;
    case COMMAND_SHOW:
        $response = $responses[253];
        $r = do_show($arg_list, $conn_list, $servers, $db);
        if ($r === FALSE)
            $response = $responses[501];
        else {
            $response .= $r;
            $response .= ".\n";
        }
        return URDD_NOERROR;
    case COMMAND_CLEANDB:
        //$response = do_cleandb($db, isset($arg_list[0])?$arg_list[0]:'');
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        $response = queue_cleandb($db, $servers, $arg, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_TIME:
        $response = $responses[260];
        $response .= show_time();
        $response .= ".\n";
        return URDD_NOERROR;
    case COMMAND_UPTIME:
        $response = $responses[259];
        $response .= show_uptime();
        $response .= ".\n";
        return URDD_NOERROR;
    case COMMAND_UPDATE:
        // check if no expire is going on and it is not already doing this action
        $response = queue_update($db, COMMAND_UPDATE, $arg_list, $username, $servers, $priority);
        return URDD_NOERROR;
    case COMMAND_GROUPS:
        $response = queue_groups($db, $servers, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_GROUP:
        $response = do_group($db, $servers, $arg_list, $username);
        return URDD_NOERROR;
    case COMMAND_DISKFREE:
        $response = $responses[256];
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        list($code, $msg) = do_diskfree($db, $arg, $username);
        $response = $responses[$code] . $msg . ".\n";
        return URDD_NOERROR;
    case COMMAND_CONTINUE:
        $response = do_pause($db, $servers, $arg_list, FALSE, $username);
        return URDD_NOERROR;
    case COMMAND_PAUSE:
        $response = do_pause($db, $servers, $arg_list, TRUE, $username);
        return URDD_NOERROR;
    case COMMAND_CANCEL:
        $response = do_cancel($db, $servers, $arg_list, $username);
        return URDD_NOERROR;
    case COMMAND_STOP:
        $response = do_stop($db, $servers, $arg_list, $username);
        return URDD_NOERROR;
    case COMMAND_PREEMPT:
        try {
            $response = do_preempt($db, $servers, $arg_list, $username);
        } catch (exception $e) {
            $response = $responses[532];
        }
        return URDD_NOERROR;
    case COMMAND_PURGE:
        // check if no update is going on and it is not already doing this action
        $response = queue_purge_expire($db, COMMAND_PURGE, $arg_list, $username, $servers, $priority);
        return URDD_NOERROR;
    case COMMAND_PURGE_RSS:
        // check if no update is going on and it is not already doing this action
        $response = queue_purge_expire($db, COMMAND_PURGE_RSS, $arg_list, $username, $servers, $priority);
        return URDD_NOERROR;
    case COMMAND_EXPIRE:
        // check if no update is going on and it is not already doing this action
        $response = queue_purge_expire($db, COMMAND_EXPIRE, $arg_list, $username, $servers, $priority);
        return URDD_NOERROR;
    case COMMAND_EXPIRE_RSS:
        // check if no update is going on and it is not already doing this action
        $response = queue_purge_expire($db, COMMAND_EXPIRE_RSS, $arg_list, $username, $servers, $priority);
        return URDD_NOERROR;
    case COMMAND_EXIT:
    case COMMAND_QUIT: 
        $conn =& $conn_list->get_conn($sock);
        write_log("Ending connection from host {$conn->get_peer_hostname()}:{$conn->get_peer_port()}");
        $response = $responses[221];
        return URDD_CLOSE_CONN;
    case COMMAND_ECHO:
        $response = $responses[254];
        $response .= " $args\n";
        $response .= ".\n";
        return URDD_NOERROR;
    case COMMAND_NOOP:
        $response = $responses[231];
        return URDD_NOERROR;
    case COMMAND_HELP:
        $help_message = do_help($arg_list, $response);
        $response .= $help_message;
        $response .= ".\n";
        return URDD_NOERROR;
    case COMMAND_STATUS:
        $response = $responses[251];
        $response .= do_status($servers, $conn_list);
        $response .= ".\n";
        return URDD_NOERROR;
    case COMMAND_SUBSCRIBE:
        $response = do_subscribe($db, $arg_list, $servers, $username);
        return URDD_NOERROR;
    case COMMAND_SUBSCRIBE_RSS:
        $response = do_subscribe_rss($db, $arg_list, $servers, $username);
        return URDD_NOERROR;
    case COMMAND_OPTIMISE:
        $response = queue_optimise($db, $servers, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_UNPAR_UNRAR:
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        $response = queue_unpar_unrar($db, '', $arg, $servers, $username, FALSE, $priority);
        return URDD_NOERROR;
    case COMMAND_CLEANDIR:
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        $response = queue_cleandir($db, $servers, $arg, $username, $priority);
        return URDD_NOERROR;   
    case COMMAND_VERSION:
        $response = $responses[262] . get_version() .' (' . get_status() . ")\n.\n";
        return URDD_NOERROR;
    case COMMAND_CHECK_VERSION:
        $response = queue_check_version($db, $servers, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_WHOAMI:
        $response = $responses[261] . $username . "\n.\n";
        return URDD_NOERROR;
    case COMMAND_PRIORITY:
        $response = do_priority($db, $arg_list, $servers, $username);
        return URDD_NOERROR;
    case COMMAND_SET:
        $response = do_set($db, $servers, $arg_list, $username);
        return URDD_NOERROR;
    case COMMAND_GETSETINFO:
        if (!isset($config['connect_urdland']) || $config['connect_urdland'] === TRUE)
            $response = queue_getsetinfo($db, $servers, $username, $priority);
        else 
            $response = $responses[533];
        return URDD_NOERROR;
    case COMMAND_SENDSETINFO:
        if (!isset($config['connect_urdland']) || $config['connect_urdland'] === TRUE)
            $response = queue_sendsetinfo($db, $servers, $username, $priority);
        else 
            $response = $responses[533];
        return URDD_NOERROR;
    case COMMAND_MOVE:
        $response = do_move($db, $servers, $arg_list, $username);
        return URDD_NOERROR;
    case COMMAND_GENSETS:
        $response = queue_gensets($db, $servers, $arg_list, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_ADDDATA:
        $response = queue_adddata($db, $servers, $arg_list, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_POST_MESSAGE:
        $response = queue_post_message($db, $servers, $arg_list, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_PARSE_NZB:
        $response = queue_parse_nzb($db, $servers, $arg_list, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_UPDATE_RSS:
        $response = queue_update_rss($db, COMMAND_UPDATE_RSS, $arg_list, $username, $servers, $priority);
        return URDD_NOERROR;
    case COMMAND_FINDSERVERS:
        $response = queue_find_servers($db, $servers, $arg_list, $username, $priority);
        return URDD_NOERROR;
    case COMMAND_START_POST: // if run from the command line it's a no-op too 
    case COMMAND_POST_ACTION: // if run from the command line it's a no-op too 
        if ($internal === FALSE) {
            $response = $responses[231];
            return URDD_NOERROR;
        } // fall thru
    case COMMAND_POST:
        $arg = isset($arg_list[0]) ? $arg_list[0] : '';
        if ($internal === FALSE) {
            $response = queue_prepare_post($db, $servers, $arg, $username, $priority);
        } else 
            $response = restart_post($db, $cmd->get_code(), $servers, $username, $arg, $priority);
        return URDD_NOERROR;
    case COMMAND_MERGE_SETS:
        if (!isset($arg_list[0]) || !isset($arg_list[1]) ) 
            $response = $responses[501];
        else 
            $response = queue_merge_sets($db, $servers, $args, $username, $priority);
        return URDD_NOERROR;   
    case COMMAND_DELETE_SET_RSS:
        if (!isset($arg_list[0])) 
            $response = $responses[501];
        else {
            try {
                queue_delete_set_rss($db, $servers, $args, $username, $priority);
                $response = $responses[200];
            } catch (exception $e) {
                $response = $responses[513];
            }
        }
        return URDD_ERROR;
    case COMMAND_DELETE_SET:
        if (!isset($arg_list[0])) 
            $response = $responses[501];
        else {
            try {
                queue_delete_set($db, $servers, $args, $username, $priority);
                $response = $responses[200];
            } catch (exception $e) {
                $response = $responses[513];
            }
        }
        return URDD_ERROR;
    default:
        $response = sprintf($responses[500], "'$cmd_str'");
        return URDD_ERROR;
    }
}


class command {
    private $command;  // command string
    private $need_auth; // must be authenticated before executing the command
    private $code; // the numeral code of the command
    private $help_msg; // text string description of the command 
    private $syntax;   // format of the command for help 
    private $need_admin; // must be admin user to exec the command
    private $need_nntp; // an nntp connection is needed 
    private $primary_nntp; // connect to the primary nntp server
    private $arg_str;   // argument string format
    private $db_intensive; // relies heavily on db interaction==> additional limitation on threads running of this type
    private $need_posting; // needs the posting capability of a nntp server
    function __construct ($cmd, $auth, $admin, $code, $need_nntp, $syntax='', $help_message='', $arg_str='', $primary_nntp=FALSE, $db_intensive= FALSE, $need_posting=FALSE)
    {
        assert(is_bool($need_nntp) && is_bool($primary_nntp) && is_bool($auth) && is_bool($admin) && is_numeric($code));
        $this->command = $cmd;
        $this->need_auth = $auth;
        $this->code = (int)$code;
        $this->help_msg = $help_message;
        $this->syntax = $syntax;
        $this->need_admin = $admin;
        $this->need_nntp = $need_nntp;
        $this->arg_str = $arg_str;
        $this->primary_nntp = $primary_nntp;
        $this->db_intensive = $db_intensive;
        $this->need_posting = $need_posting;
    }
    function needs_auth() { return $this->need_auth;}
    function match_command($str) { return strtoupper($str) === $this->command; }
    function get_code() { return $this->code;}
    function get_syntax() { return $this->syntax;}
    function get_helpmessage() { return $this->help_msg;}
    function get_command() { return $this->command;}
    function needs_admin() { return $this->need_admin;}
    function needs_nntp() { return $this->need_nntp;}
    function needs_posting() { return $this->need_posting;}
    function get_arg_str() { return $this->arg_str;}
    function primary_nntp() { return $this->primary_nntp;}
    function db_intensive() { return $this->db_intensive;}
};

$commands_list_1 = array( // need to optimize so that $commands_list[$cmd] is the one we need
    new command('!!', TRUE, FALSE, COMMAND_REPEAT_LAST_COMMAND, FALSE, '!!', 'Repeat last command', '', FALSE, FALSE, FALSE),
    new command('ADDDATA', TRUE, FALSE, COMMAND_ADDDATA, FALSE, 'ADDDATA DLID SET SETID [PREVIEW]', 'Adds a set with SETID to a download with DLID', '%n %n SET %n', FALSE, FALSE, FALSE),
    new command('CANCEL', TRUE, FALSE, COMMAND_CANCEL, FALSE, 'CANCEL ID|ALL', 'Cancel action with ID, or cancel all actions', '%n', FALSE, FALSE, FALSE),
    new command('CHECK_VERSION', TRUE, FALSE, COMMAND_CHECK_VERSION, FALSE, 'CHECK_VERSION', 'Checks whether a new version is available', '', FALSE, FALSE, FALSE),
    new command('CLEANDB', TRUE, TRUE, COMMAND_CLEANDB, FALSE, 'CLEANDB [ALL|AGE|NOW]', 'Remove download items that are finished, or failed; ALL removes all download items (not regarding statusz), Age gives a number of days since when items can be removed, now removes all items with regard to status', '[%s]', FALSE, TRUE, FALSE),
    new command('CLEANDIR', TRUE, TRUE, COMMAND_CLEANDIR, FALSE, 'CLEANDIR ALL|PREVIEW|TMP|NZB', 'Remove all files older than one day form the downloaddir/tmp or downloaddir/preview or downloaddir/nzb', '%s', FALSE, FALSE, FALSE),
    new command('CONTINUE', TRUE, FALSE, COMMAND_CONTINUE, FALSE, 'CONTINUE ID|ALL', 'Restarted a paused action ID, or all actions', '(%n|%s)', FALSE, FALSE, FALSE),
    new command('DISKFREE', TRUE, FALSE, COMMAND_DISKFREE, FALSE, 'DISKFREE', 'Shows the available disk space', '', FALSE, FALSE, FALSE),
    new command('DELETE_SET', TRUE, TRUE, COMMAND_DELETE_SET, FALSE, 'DELETE_SET ID', 'Remove a group set', '%n', FALSE, FALSE, FALSE),
    new command('DELETE_SET_RSS', TRUE, TRUE, COMMAND_DELETE_SET_RSS, FALSE, 'DELETE_SET_RSS ID', 'Remove an RSS set', '%n', FALSE, FALSE, FALSE),
    new command('DOWNLOAD', TRUE, FALSE, COMMAND_DOWNLOAD, TRUE, 'DOWNLOAD [ID|PREVIEW]', 'Starts a new download or restarts a download with ID', '[%n]', FALSE, FALSE, FALSE),
    new command('DOWNLOAD_ACTION', TRUE, FALSE, COMMAND_DOWNLOAD_ACTION, TRUE, 'DOWNLOAD_ACTION', 'No operation (used interally)', '', FALSE, FALSE, FALSE),
    new command('ECHO', TRUE, FALSE, COMMAND_ECHO, FALSE, 'ECHO text', 'Echoes the given text', '%s', FALSE, FALSE, FALSE),
    new command('EXIT', FALSE, FALSE, COMMAND_EXIT, FALSE, 'EXIT', 'End the connection', '', FALSE, FALSE, FALSE),
    new command('EXPIRE', TRUE, TRUE, COMMAND_EXPIRE, FALSE, 'EXPIRE ID|ALL', 'Expire old messages in group ID or in all groups', '(%n|%s)', FALSE, TRUE, FALSE),
    new command('EXPIRE_RSS', TRUE, TRUE, COMMAND_EXPIRE_RSS, FALSE, 'EXPIRE_RSS ID|ALL', 'Expire old feed informatien for feed n or in all feeds', '(%n|%s)', FALSE, TRUE, FALSE),
    new command('FINDSERVERS', TRUE, TRUE, COMMAND_FINDSERVERS, TRUE, 'FINDSERVERS', 'Autoconfigure usenet servers', '', FALSE, FALSE, FALSE),
    new command('GENSETS', TRUE, TRUE, COMMAND_GENSETS, FALSE, 'GENSETS ID', 'Generate sets for group ID', '%n', FALSE, TRUE, FALSE),
    new command('GETSETINFO', TRUE, TRUE, COMMAND_GETSETINFO, FALSE, 'GETSETINFO', 'Get the extended set information from Urdland.com', '', FALSE, FALSE, FALSE),
    new command('GROUP', TRUE, FALSE, COMMAND_GROUP, FALSE, 'GROUP ID', 'Show information about group with ID', '%n', FALSE, FALSE, FALSE),
    new command('GROUPS', TRUE, TRUE, COMMAND_GROUPS, TRUE, 'GROUPS', 'Update the list of available newsgroups', '', TRUE, FALSE, FALSE),
    new command('HELP', FALSE, FALSE, COMMAND_HELP, FALSE, 'HELP [Command]', 'Show all valid commands or syntax of one command', '[%s]', FALSE, FALSE, FALSE),
    new command('MAKE_NZB', TRUE, FALSE, COMMAND_MAKE_NZB, FALSE, 'MAKE_NZB', 'Create an NZB file', '', FALSE, TRUE, FALSE),
    new command('MERGE_SETS', TRUE, FALSE, COMMAND_MERGE_SETS, FALSE, 'MERGE_SETS setid1 setid2', 'Merges sets setid2 into setid1', '%s %s', FALSE, FALSE, FALSE),
    new command('MOVE', FALSE, FALSE, COMMAND_MOVE, FALSE, 'MOVE UP|DOWN <ID>', 'Move an item up in the queue', ' (up|down) [%n]', FALSE, FALSE, FALSE),
    new command('NOOP', TRUE, FALSE, COMMAND_NOOP, FALSE, 'NOOP', 'No operation', '', FALSE, FALSE, FALSE),
    new command('OPTIMISE', TRUE, TRUE, COMMAND_OPTIMISE, FALSE, 'OPTIMISE', 'Optimise the databases', '', FALSE, TRUE, FALSE),
    new command('PARSE_NZB', TRUE, FALSE, COMMAND_PARSE_NZB, FALSE, 'PARSE_NZB [dlid] url [starttime]', 'read and NZB file from the given URL', '[%n] %s [%n]', FALSE, FALSE, FALSE),
    new command('PASS', FALSE, FALSE, COMMAND_PASS, FALSE, 'PASS [hash:]password', 'Enter a password, optionally as sha256 hash', '%s', FALSE, FALSE, FALSE),
    new command('PAUSE', TRUE, FALSE, COMMAND_PAUSE, FALSE, 'PAUSE ID|ALL', 'Pause action ID or all actions', '%s', FALSE, FALSE, FALSE),
    new command('POST', TRUE, FALSE, COMMAND_POST, FALSE, 'POST ID', 'Post the files identified by ID in the postinfo table', '%s %s', FALSE, FALSE, FALSE),
    new command('POST_MESSAGE', TRUE, FALSE, COMMAND_POST_MESSAGE, TRUE, 'POST_MESSAGE MESSAGE_ID', 'Post a text message to the group', '%n', FALSE, FALSE, TRUE),
    new command('POST_ACTION', TRUE, FALSE, COMMAND_POST_ACTION, TRUE, 'POST_ACTION', 'No operation (internal use)', '', FALSE, FALSE, TRUE),
    new command('PREEMPT', TRUE, FALSE, COMMAND_PREEMPT, FALSE, 'PREEMPT ID1 ID2', 'Start the process with ID1 and push process with ID2 back on the queue', '%n %n', FALSE, FALSE, FALSE),
    new command('PRIORITY', TRUE, FALSE, COMMAND_PRIORITY, FALSE, 'PRIORITY ID PRIORITY', 'Set the priority of a process with ID1 to priority PRIORITY', '%n %n', FALSE, FALSE, FALSE),
    new command('PURGE', TRUE, TRUE, COMMAND_PURGE, FALSE, 'PURGE ID|ALL', 'Remove all articles from a group ID or from all groups', '%n|%s', FALSE, FALSE, FALSE),
    new command('PURGE_RSS', TRUE, TRUE, COMMAND_PURGE_RSS, FALSE, 'PURGE_RSS ID|ALL', 'Remove all links from a feed ID or from all feeds', '%n|%s', FALSE, FALSE, FALSE),
    new command('QUIT', FALSE, FALSE, COMMAND_QUIT, FALSE, 'QUIT', 'End the connection', '', FALSE, FALSE, FALSE),
    new command('RESTART', TRUE, TRUE, COMMAND_RESTART, FALSE, 'RESTART', 'Restart URDD', '', FALSE, FALSE, FALSE),
    new command('SCHEDULE', TRUE, FALSE, COMMAND_SCHEDULE, FALSE, 'SCHEDULE <command> @ \'<time>\' [# recurrence]', 'Run the given command at the given time, optionally repeat every recurrence.', '%l @ %t [# %n]', FALSE, FALSE, FALSE),
    new command('SENDSETINFO', TRUE, TRUE, COMMAND_SENDSETINFO, FALSE, 'SENDSETINFO', 'Send the extended set information to Urdland.com', '', FALSE, FALSE, FALSE),
    new command('SET', TRUE, TRUE, COMMAND_SET, FALSE, 'SET LOG_LEVEL <value>|SCHEDULES <bool>|SERVER <id> <priority>|PREFERRED <id>', 'Set the internal parameter to the given value.', '%s %s [%s]', FALSE, FALSE, FALSE),
    new command('SHOW', TRUE, FALSE, COMMAND_SHOW, FALSE, 'SHOW ALL|QUEUE|NEWSGROUPS|SUBSCRIBED|FEEDS|USERS|THREADS|JOBS|CONFIG|VERSION|SERVERS|TESTS|LOAD', 'Output all actions on the queue, all newsgroups, all subscribed newsgroups, rss feeds, all logged in users, all running actions, all scheduled jobs, the running configuration or all servers, the results of the performed tests at startup, the system load; ALL outputs the threads, queue, jobs, users and servers', '%s', FALSE, FALSE, FALSE),
    new command('SHUTDOWN', TRUE, TRUE, COMMAND_SHUTDOWN, FALSE, 'SHUTDOWN', 'Shutdown URDD', '', FALSE, FALSE, FALSE),
    new command('START_POST', TRUE, FALSE, COMMAND_START_POST, TRUE, 'START_POST', 'No operation (internal use)', '', FALSE, FALSE, TRUE),
    new command('STATUS', TRUE, FALSE, COMMAND_STATUS, FALSE,  'STATUS', 'Shows an overview of URDD\'s status', '', FALSE, FALSE, FALSE),
    new command('STOP', TRUE, FALSE, COMMAND_STOP, FALSE, 'STOP ID|ALL', 'Stop a download with ID, or all download ', '(%n|%s)' , FALSE, FALSE, FALSE),
    new command('SUBSCRIBE', TRUE, TRUE, COMMAND_SUBSCRIBE, FALSE,  'SUBSCRIBE ID OFF|ON [Expire] ', 'Subscribe or unsubcribe to group ID with optional expire time in day ', '%n %s [%n]', FALSE, FALSE, FALSE),
    new command('SUBSCRIBE_RSS', TRUE, TRUE, COMMAND_SUBSCRIBE_RSS, FALSE, 'SUBSCRIBE_RSS ID OFF|ON [Expire]', 'Subscribe or unsubcribe to an rss feed with optional expire time in day ', '%n %s [%n]', FALSE, FALSE, FALSE),
    new command('TIME', TRUE, FALSE, COMMAND_TIME, FALSE, 'TIME', 'Return the local time of the URD daemon in RFC 2822 forma ', '', FALSE, FALSE, FALSE),
    new command('UNPAR_UNRAR', TRUE, FALSE,  COMMAND_UNPAR_UNRAR, FALSE, 'UNPAR_UNRAR ID', 'Start to verify the downloaded files, unrar them and delete the rar and par2 file ', '%n', FALSE, FALSE, FALSE),
    new command('UNSCHEDULE', TRUE, FALSE, COMMAND_UNSCHEDULE, FALSE, 'UNSCHEDULE ID|ALL|COMMAND (ARG|__ALL)', 'Remove a scheduled job with ID, all jobs, or a command with an argument or all of the jobs for that comman ', '(%n|%c|%s) %s)', FALSE, FALSE, FALSE),
    new command('UPDATE', TRUE, TRUE, COMMAND_UPDATE, TRUE, 'UPDATE ID|ALL', 'Update the articles is news group ID or all group ', '(%n|%s)', TRUE, FALSE, FALSE),
    new command('UPDATE_RSS', TRUE, TRUE, COMMAND_UPDATE_RSS, FALSE, 'UPDATE_RSS ID|ALL', 'Update the rss feed with ID or all feeds ', '(%n|%s)', FALSE, FALSE, FALSE),
    new command('UPTIME', TRUE, FALSE, COMMAND_UPTIME, FALSE, 'UPTIME', 'Return the uptime of the URD daemo ', '', FALSE, FALSE, FALSE),
    new command('USER', FALSE, FALSE, COMMAND_USER, FALSE, 'USER username', 'Enter a username to login', '%s', FALSE, FALSE, FALSE),
    new command('VERSION', TRUE, FALSE, COMMAND_VERSION, FALSE, 'VERSION', 'Returns the current version', '', FALSE, FALSE, FALSE),
    new command('WHOAMI', TRUE, FALSE, COMMAND_WHOAMI, FALSE, 'WHOAMI', 'Returns the users login name', '', FALSE, FALSE, FALSE)
);

foreach ($commands_list_1 as $cmd) {
    $commands_list[$cmd->get_code()] = $cmd;
    $commands_list[$cmd->get_command()] = $cmd;
}
unset($commands_list_1);


function get_command_code($str)
{
    global $commands_list;
    $str = strtoupper($str);
    if (isset($commands_list[$str]))
        return $commands_list[$str]->get_code();

    return FALSE;
}


function match_command($str)
{
    global $commands_list;

    $str = strtoupper($str);
    if (isset($commands_list[$str]))
        return $commands_list[$str];
    return FALSE;
}


function compare_command($str, $cmd)
{
    global $commands_list;
    $str = strtoupper($str);
    if (isset($commands_list[$cmd]))
        return $commands_list[$cmd]->get_command() == $str;
    return FALSE;
}


function get_command($cmd)
{// get the commandstring for a command code 
    global $commands_list;
    if (isset($commands_list[$cmd]))
        return $commands_list[$cmd]->get_command();
    return FALSE;
}


function get_help_all()
{
    global $commands_list;
    $msg = '';
    foreach ($commands_list as $k=>$c) {
        if(is_numeric($k)) {
            $msg .= $c->get_syntax() . "\n";
            $msg .= $c->get_helpmessage() . "\n\n";
        }
    }
    return $msg;
}
function get_command_posting($cmd)
{//return if a command needs an nntp connection
    global $commands_list;
    if (isset($commands_list[$cmd]))
        return $commands_list[$cmd]->needs_posting();
    return FALSE;
}

function get_command_nntp($cmd)
{//return if a command needs an nntp connection
    global $commands_list;
    if (isset($commands_list[$cmd]))
        return $commands_list[$cmd]->needs_nntp();
    return FALSE;
}

function get_command_primary_nntp($cmd)
{//return if a command needs an nntp connection
    global $commands_list;
    if (isset($commands_list[$cmd]))
        return $commands_list[$cmd]->primary_nntp();
    return FALSE;
}

function get_command_db_intensive($cmd)
{//return if a command needs an nntp connection
    global $commands_list;
    if (isset($commands_list[$cmd]))
        return $commands_list[$cmd]->db_intensive();
    return FALSE;
}

?>
